package Syntaxe;

import java.util.LinkedList;

public class Matrice {
	public Fraction[][] matrice;
	public int M;
	public int N;// matrice a taille M*N

	public Matrice(int m, int n) {
		matrice = new Fraction[m][n];
		M = m;
		N = n;
	}

	public Matrice(Fraction[][] m) {
		matrice = m;
		if (m != null) {
			M = m.length;
			if (m[0] != null) {
				N = m[0].length;
			} else {
				N = 0;
			}
		} else {
			N = 0;
		}
	}

	public Matrice(Invariant inv) {
		LinkedList<Expression> listCopy = inv.listExpr;
		while (!listCopy.isEmpty()) {
			listCopy.poll();

		}
	}

	public static Matrice zeros(int n) {
		// to get a matrix zeros n*n
		Matrice I = new Matrice(n, n);
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < n; j++) {
				I.matrice[i][j] = new Fraction(0);
			}
		}
		return I;
	}
	
	public static Matrice zeros(int m,int n) {
		// to get a matrix zeros m*n
		Matrice I = new Matrice(m, n);
		for (int i = 0; i < m; i++) {
			for (int j = 0; j < n; j++) {
				I.matrice[i][j] = new Fraction(0);
			}
		}
		return I;
	}
	

	public static Matrice eye(int n) {
		// to get a matrix indentity I_n
		Matrice I = Matrice.zeros(n);
		for (int i = 0; i < n; i++) {
			I.matrice[i][i] = new Fraction(1);
		}
		return I;
	}

	public Fraction[] colonne(int j){
		// collone j de Matrice 
		Fraction[] col=new Fraction[M];
		for (int i=0;i<M;i++){
			col[i]=matrice[i][j];
		}
		return col;
	}
	public static Matrice fusion(Matrice m1, Matrice m2) {
		// to get a matrix [M1,M2]
		int M1 = m1.M;
		int N1 = m1.N;
		int M2 = m2.M;
		int N2 = m2.N;
		if (M1 == M2) {
			Matrice I = new Matrice(M1, N1 + N2);
			for (int i = 0; i < M1; i++) {
				for (int j = 0; j < N1; j++) {
					I.matrice[i][j] = m1.matrice[i][j];
				}
				for (int j = 0; j < N2; j++) {
					I.matrice[i][j + N1] = m2.matrice[i][j];
				}
			}
			return I;
		} else {
			System.out.println("Problem de taille de matrice");
			return null;
		}
	}

	public static Matrice fusion(Matrice m1, Fraction[] m2) {
		// to get a matrix [M1,M2]
		int M1 = m1.M;
		int N1 = m1.N;
		int M2 = m2.length;

		if (M1 == M2) {
			Matrice I = new Matrice(M1, N1 + 1);
			for (int i = 0; i < M1; i++) {
				for (int j = 0; j < N1; j++) {
					I.matrice[i][j] = m1.matrice[i][j];
				}

				I.matrice[i][N1] = m2[i];
			}
			return I;
		} else {
			System.out.println("Problem de taille de matrice");
			return null;
		}
	}

	public Fraction valeur(int i, int j) {
		// valeur de matrice(i,j)
		return matrice[i][j];
	}
//TODO
	public void LigneUnify(int i0, int j0) {
		// calcul de ligne, tel que matrice(i0,j0)=1;k!=i0, matrice(k,j0)=0
		// i0123... not iO!
		if (!matrice[i0][j0].isZero()) {

			Fraction c = matrice[i0][j0];

			for (int j = 0; j < N; j++) {
				matrice[i0][j] = matrice[i0][j].divise(c);

			}

			for (int i = 0; i < M; i++) {
				if (i != i0) {
					c = matrice[i][j0];
					for (int j = 0; j < N; j++) {
						matrice[i][j] = matrice[i][j].soustraire(matrice[i0][j]
								.multiple(c));
					}
				}
			}
		}
	}

	public Matrice subColonne(int n1, int n2) {
		// n2>=n1
		// matrice de colonne n1 -> n2 (n1,n2 inclus)
		Matrice m = new Matrice(M, n2 - n1+1);
		for (int i = 0; i < M; i++) {
			for (int j = 0; j <= n2 - n1; j++) {
				m.matrice[i][j] = matrice[i][n1 + j];
			}
		}
		return m;

	}
	public Matrice subLigne(int n1, int n2) {
		// n2>=n1
		// matrice de ligne n1 -> n2 (n1,n2 inclus)
		Matrice m = new Matrice( n2 - n1+1,N);
		for (int i = 0; i <= n2 - n1; i++) {
			
				m.matrice[i] = matrice[i+n1];
			
		}
		return m;

	}

	public void MultiLigne(int i, Fraction f) {
		// le i eme ligne multipler par f
		for (int j = 0; j < N; j++) {
			matrice[i][j] = matrice[i][j].multiple(f);
		}
	}

	public Matrice MultiNum(Fraction f) {
		// matrice multipler par f
		Matrice m = new Matrice(M, N);
		for (int i = 0; i < M; i++) {
			for (int j = 0; j < N; j++) {
				m.matrice[i][j] = matrice[i][j].multiple(f);
			}
		}
		return m;
	}

	public Matrice MultiNum(int f) {
		// matrice multipler par f
		Matrice m = new Matrice(M, N);
		for (int i = 0; i < M; i++) {
			for (int j = 0; j < N; j++) {
				m.matrice[i][j] = matrice[i][j].multiple(f);
			}
		}
		return m;
	}

	public void MultiLigne(int i, int f) {
		// le i eme ligne multipler par f
		for (int j = 0; j < N; j++) {
			matrice[i][j] = matrice[i][j].multiple(f);
		}
	}

	public double[][] transToDouble() {
		double[][] md = new double[M][N];
		for (int i = 0; i < M; i++) {
			for (int j = 0; j < N; j++) {
				md[i][j] = matrice[i][j].toDouble();
			}

		}
		return md;
	}

	public void AfficheMatrice() {

		for (int i = 0; i < M; i++) {
			for (int j = 0; j < N; j++) {
				matrice[i][j].print();
				System.out.print(", ");
			}
			System.out.println(";");
		}
		System.out.println();
	}
	
	public void AfficheDouble() {

		for (int i = 0; i < M; i++) {
			for (int j = 0; j < N; j++) {
				System.out.print(matrice[i][j].toDouble()+", ");
				
			}
			System.out.println(";");
		}
		System.out.println();
	}
}
